import json
import os
import pandas as pd
from datetime import datetime
from collections import defaultdict


def fmt_ts(ts):
    return datetime.fromtimestamp(ts / 1000).strftime('%Y-%m-%d  %H:%M:%S')


def parse_time_info(report_path):
    build_time_map = defaultdict(lambda: {'min_start': float('inf'), 'max_stop': 0})
    history_path = os.path.join(report_path, "history", "history.json")

    with open(history_path, 'r', encoding='utf-8') as f:
        for test_suite in json.load(f).values():
            for item in test_suite.get('items', []):
                raw_url = item.get('reportUrl', '')
                time_info = item.get('time', {})
                if '/allure' not in raw_url or 'start' not in time_info or 'stop' not in time_info:
                    continue
                clean_url = raw_url.split('/allure')[0] + '/allure'
                start_ts, stop_ts = time_info['start'], time_info['stop']
                if start_ts < build_time_map[clean_url]['min_start']:
                    build_time_map[clean_url]['min_start'] = start_ts
                if stop_ts > build_time_map[clean_url]['max_stop']:
                    build_time_map[clean_url]['max_stop'] = stop_ts
    result = {}
    for url, info in build_time_map.items():
        result[url] = {
            '开始时间': fmt_ts(info['min_start']),
            '结束时间': fmt_ts(info['max_stop'])
        }
    return result


def parse_test_stats(report_path):
    trend_path = os.path.join(report_path, "history", "history-trend.json")
    duration_path = os.path.join(report_path, "history", "duration-trend.json")

    with open(duration_path, 'r') as f:
        duration_map = {}
        for item in json.load(f):
            if 'buildOrder' in item:
                duration_val = item.get('data', {}).get('duration',0)
                duration_map[item['buildOrder']] = duration_val

    stats_list = []
    with open(trend_path, 'r') as f:
        for build in json.load(f):
            build_order = build.get('buildOrder')
            url = build.get('reportUrl', '')
            if build_order is None or not url:
                continue
            stats = build.get('data', {})
            total = stats.get('total', 0)
            passed = stats.get('passed', 0)
            pass_rate = round((passed / total) * 100, 2) if total else 0
            ms = duration_map.get(build_order, 0)
            h, r = divmod(ms, 3600 * 1000)
            m, s = divmod(r, 60 * 1000)
            duration = f"{int(h)}小时{int(m)}分{int(s // 1000)}秒"

            stats_list.append({
                'allure报告URL': url,
                '总用例数': total,
                '通过用例数': passed,
                '失败用例数': stats.get('failed', 0),
                'broken用例数': stats.get('broken', 0),
                '跳过用例数': stats.get('skipped', 0),
                '通过率(%)': pass_rate,
                '总耗时': duration
            })
    return stats_list

#保存结果
def merge_save_result(time_info, test_stats, output_file):
    new_data = []
    for stat in test_stats:
        url = stat['allure报告URL']
        if url in time_info:
            new_item = {**stat, **time_info[url]}
            new_data.append(new_item)
    if not new_data:
        return

    cols = ['allure报告URL', '开始时间', '结束时间', '总用例数', '通过用例数', '失败用例数',
            'broken用例数','跳过用例数', '通过率(%)', '总耗时']
    new_df = pd.DataFrame(new_data).reindex(columns=cols)
    new_df['通过率(%)'] = new_df['通过率(%)'].apply(lambda x: f"{x:.2f}%")

    if os.path.exists(output_file):
        history_df = pd.read_excel(output_file)
        combined_df = pd.concat([new_df, history_df], ignore_index=True)
        combined_df = combined_df.drop_duplicates(subset=['allure报告URL'], keep='first')
        # 保存合并后的数据
        combined_df.to_excel(output_file, index=False, engine='openpyxl')
        print(f"添加{len(new_df)}条数据，总计{len(combined_df)}条数据，保存至：{output_file}")
    else:
        new_df.to_excel(output_file, index=False)
        print(f"保存{len(new_df)}条数据至：{output_file}")


def main(report_path="allure-report", output_file="自动化测试统计结果.xlsx"):
    merge_save_result(
        parse_time_info(report_path),
        parse_test_stats(report_path),
        output_file
    )

main()

# if __name__ == "__main__":
#     # report_path = r"C:\Users\Administrator\Downloads\allure-report (3)\allure-report"
#     main()